package com.lakienko.igor.random.values.rest.convert;

import com.lakienko.igor.random.values.domain.entity.CategoryEntity;
import com.lakienko.igor.random.values.domain.entity.ValueEntity;
import com.lakienko.igor.random.values.rest.model.in.CategoryRestIn;
import com.lakienko.igor.random.values.rest.model.in.ValueRestIn;
import com.lakienko.igor.random.values.rest.model.out.CategoryRestOut;
import com.lakienko.igor.random.values.rest.model.out.ValueRestOut;
import com.lakienko.igor.random.values.service.model.in.CategoryIn;
import com.lakienko.igor.random.values.service.model.in.ValueIn;
import com.lakienko.igor.random.values.service.model.out.CategoryOut;
import com.lakienko.igor.random.values.service.model.out.ValueOut;

import java.util.Objects;
import java.util.UUID;

public interface RandomsConverters {

    default CategoryRestOut convert(CategoryOut out) {
        return CategoryRestOut.builder()
                .id(out.getId())
                .name(out.getName())
                .description(out.getDescription())
                .values(out.getValues().stream()
                        .map(this::convert)
                        .toList())
                .build();
    }

    default CategoryIn convert(CategoryRestIn in) {
        return CategoryIn.builder()
                .name(in.getName())
                .description(in.getDescription())
                .build();
    }

    default CategoryIn convert(CategoryRestIn in, UUID categoryId) {
        return CategoryIn.builder()
                .id(categoryId)
                .name(in.getName())
                .description(in.getDescription())
                .build();
    }

    default ValueRestOut convert(ValueOut out) {
        return ValueRestOut.builder()
                .id(out.getId())
                .name(out.getName())
                .description(out.getDescription())
                .categoryId(out.getCategoryId())
                .build();
    }

    default ValueIn convert(ValueRestIn restIn) {
        return ValueIn.builder()
                .name(restIn.getName())
                .description(restIn.getDescription())
                .categoryId(restIn.getCategoryId())
                .build();
    }

    default ValueIn convert(ValueRestIn restIn, UUID valueId) {
        return ValueIn.builder()
                .id(valueId)
                .name(restIn.getName())
                .description(restIn.getDescription())
                .categoryId(restIn.getCategoryId())
                .build();
    }

    default CategoryOut convertCategoryEntityToCategoryOut(CategoryEntity categoryEntity) {
        return CategoryOut.builder()
                .id(categoryEntity.getId())
                .name(categoryEntity.getName())
                .description(categoryEntity.getDescription())
                .values(categoryEntity.getValues().stream()
                        .map(this::convertCategoryEntityToCategoryOut)
                        .toList())
                .build();
    }

    default CategoryEntity convertCategoryInToCategoryOut(CategoryIn categoryIn) {
        return CategoryEntity.builder()
                .id(Objects.isNull(categoryIn.getId()) ? UUID.randomUUID() : categoryIn.getId())
                .name(categoryIn.getName())
                .description(categoryIn.getDescription())
                .build();
    }

    default ValueOut convertCategoryEntityToCategoryOut(ValueEntity valueEntity) {
        return ValueOut.builder()
                .id(valueEntity.getId())
                .name(valueEntity.getName())
                .description(valueEntity.getDescription())
                .categoryId(valueEntity.getCategory().getId())
                .build();
    }

    default ValueEntity convertCategoryInToCategoryOut(ValueIn valueIn, CategoryEntity categoryEntity) {
        return ValueEntity.builder()
                .id(Objects.isNull(valueIn.getId()) ? UUID.randomUUID() : valueIn.getId())
                .name(valueIn.getName())
                .description(valueIn.getDescription())
                .category(categoryEntity)
                .build();
    }
}
